package chat

import (
	"fmt"
	"log"
	"strings"
	"sync"
	"time"
)

//MaxHisLen max history len
const MaxHisLen = 50

//MaxQueueLen max queue len
const MaxQueueLen = 1024

var Mgr *ChatMgr

//ChatMgr chat mgr
type ChatMgr struct {
	hLock    sync.Mutex
	history  []*Message                  //save the message history
	in       chan *Message               //recive
	notifyFn func(data []*Message) error // notifyFn
	stats    *stats
}

func init() {
	mgr := &ChatMgr{
		history: make([]*Message, 0, MaxHisLen),
		in:      make(chan *Message, MaxQueueLen),
		stats:   &stats{slot: make([]*slot, 0, 6)},
	}
	go mgr.task()
	Mgr = mgr
}

func (mgr *ChatMgr) SetCallBack(cb func(data []*Message) error) {
	mgr.notifyFn = cb
}

//Receive receive message
func (mgr *ChatMgr) Receive(msg *Message) {
	select {
	case mgr.in <- msg:
	}
}

func (mgr *ChatMgr) Top() string {
	mgr.hLock.Lock()
	defer mgr.hLock.Unlock()
	return mgr.stats.Top()
}

func (mgr *ChatMgr) addHistory(data []*Message) {
	mgr.hLock.Lock()
	defer mgr.hLock.Unlock()
	mgr.history = append(mgr.history, data...)
	if len(mgr.history) > MaxHisLen {
		mgr.history = mgr.history[len(mgr.history)-MaxHisLen:]
	}
	for _, m := range data {
		mgr.stats.CountWords(strings.Split(string(m.Data), " "))
	}
}
func (mgr *ChatMgr) History() (data []*Message) {
	mgr.hLock.Lock()
	defer mgr.hLock.Unlock()
	data = mgr.history
	return data
}

func (mgr *ChatMgr) task() {
	defer func() {
		if x := recover(); x != nil {
			log.Println(x)
		}
	}()
	tk := time.NewTicker(1 * time.Second)
	for {
		select {
		case <-tk.C:
			length := len(mgr.in)
			if length == 0 {
				continue
			}
			data := make([]*Message, 0, length)
			for i := 0; i < length; i++ {
				if m, ok := <-mgr.in; !ok {
					break
				} else {
					data = append(data, m)
				}
			}
			mgr.addHistory(data)
			if mgr.notifyFn == nil {
				fmt.Println("chat notify fn not register")
				continue
			}
			mgr.notifyFn(data)
		}
	}
}
